﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using System.Xml.Linq;


namespace ControlExplorer
{
    public class C1FacebookShareButton : HyperlinkButton
    {
        #region ** Title

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Title.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(C1FacebookShareButton), new PropertyMetadata(""));

        #endregion
        #region ** Counter

        public string Counter
        {
            get { return (string)GetValue(CounterProperty); }
            set { SetValue(CounterProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Counter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CounterProperty =
            DependencyProperty.Register("Counter", typeof(string), typeof(C1FacebookShareButton), new PropertyMetadata("0"));


        #endregion

        #region ** Uri

        public static readonly DependencyProperty UrlProperty =
          DependencyProperty.Register("Url", typeof(string), typeof(C1FacebookShareButton),
          new PropertyMetadata(null, OnUriChanged));

        public string Url
        {
            get { return (string)GetValue(UrlProperty); }
            set { SetValue(UrlProperty, value); }
        }

        static void OnUriChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            var button = (C1FacebookShareButton)sender;
            button.UpdateUri();
        }

        #endregion

        #region ** constructor

        public C1FacebookShareButton()
        {
            DefaultStyleKey = typeof(C1FacebookShareButton);
            _wc = new WebClient();
        }

        #endregion

        #region ** implementation

        const string svcurl = @"http://api.facebook.com/restserver.php?method=links.getStats&urls={0}";
    //    const string navurl = @"http://www.facebook.com/sharer.php?u={0}"; // <<IP>> old-style parameters, don't allow setting title any more
        const string navurl = @"http://www.facebook.com/sharer/sharer.php?s=100&p[title]={1}&p[url]={0}"; 
        
        WebClient _wc;
        int maxretries = 10;
        int retry = 0;


        void UpdateUri()
        {
            _wc.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(_wc_DownloadStringCompleted);
            _wc.CancelAsync();
            retry = 0;
            BeginDownload();
        }

        void BeginDownload()
        {
            if (_wc.IsBusy)
            {
                _wc.CancelAsync();
                return;
            }
            if (Url != null)
            {
                string s = string.Format(svcurl, Uri.EscapeUriString(Url.ToString()));
                _wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(_wc_DownloadStringCompleted);
                _wc.DownloadStringAsync(new Uri(s));
            }
        }

        void _wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            _wc.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(_wc_DownloadStringCompleted);
            if (!e.Cancelled && e.Error == null)
            {
                Counter = GetCount(e.Result).ToString();
            }
            else
            {
                if (retry++ < maxretries)
                    BeginDownload();
            }
        }

        int GetCount(string xml)
        {
            int cnt = 0;
            if (!string.IsNullOrEmpty(xml))
            {
                XDocument doc = XDocument.Parse(xml);
                XNamespace ns = doc.Root.GetDefaultNamespace();
                var links = doc.Element(ns + "links_getStats_response");
                if (links != null)
                {
                    var link = links.Element(ns + "link_stat");
                    if (link != null)
                    {
                        var share_count = link.Element(ns + "share_count");
                        if (share_count != null)
                        {
                            int.TryParse(share_count.Value, out cnt);
                        }
                        /* <<IP>> can count likes as well (but don't see an easy way to add 'Like' button)
                        var like_count = link.Element(ns + "like_count");
                        if (like_count != null)
                        {
                            int cnt1 = 0;
                            int.TryParse(like_count.Value, out cnt1);
                            cnt += cnt1;
                        }*/
                    }
                }
            }

            return cnt;
        }

        private Uri GetNavigateUrl()
        {
            // <<IP>> escape strings as data, not as uri. In other case relative links (with '#' symbol) won't work
            return new Uri(string.Format(navurl, Uri.EscapeDataString(Url), Uri.EscapeDataString(Title)), UriKind.Absolute);
        }

        #endregion

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            UpdateUri();
        }

        protected override void OnClick()
        {
            if (!string.IsNullOrEmpty(Url))
            {
                this.NavigateUri = GetNavigateUrl();
                this.TargetName = "_blank";
                base.OnClick();
            }
        }
    }
}
